#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
Created on 21 jun 2011

@author: Joakim Lindskog

Copyright (c) 2011 Joakim Lindskog

This file is part of MyGarden.

    MyGarden is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MyGarden is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MyGarden.  If not, see <http://www.gnu.org/licenses/>.
'''
from cocos import scene, layer, sprite, text, actions, euclid
from cocos.director import director
import pyglet, bed, menu, random, util, weather, time, os, kytten, events
from pyglet.window import key
from gardenbase import gardensprite
from util import config
from operator import attrgetter
from gardenbase import dialog_node

class Game(layer.Layer):
    '''
    The active in-game state
    '''
    _instance = None
    _initiated = False
    is_event_handler = True
    
    # Starting values
    START_SECONDS_PER_DAY = 4.0
    START_DAY = 1
    START_MONTH = 0
    START_YEAR = 1
    START_YEAR_SCORE = 0
    START_TOTAL_SCORE = 0
    
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Game, cls).__new__(
                                cls, *args, **kwargs)
        return cls._instance

    def __init__(self, tutorial=False, language_changed=False):
        '''
        Constructor
        '''
        if Game._initiated:
            return
        else:
            Game._initiated = True
        super(Game, self).__init__();
        
        # Scene
        self.scene = scene.Scene()
        self.scene.add(self, z=0)
        self.paused = True
        self._counter = 0.0
        self.finished = False
        
        # Set to starting values
        self.resetValues()
        self.total_score = Game.START_TOTAL_SCORE
        
        # Selection
        self.selected_seed = None
        self.selected_tool = None
        self.mouse_info_image = None
        
        # Weather
        self.weather = weather.get_weather(self)
        
        # Tutorial
        if self.year == 1 and tutorial:
            self.tutorial = events.Tutorial(self)
        
        # Loading layer
        self.loading_layer = Loader()
        self.add(self.loading_layer, 300)
        director.push(self.scene)
        pyglet.clock.schedule_once(lambda dt: self.setup(language_changed), .5)
        
    def setup(self, language_changed):
        '''
        Sets up the layers and possibly starts the tutorial
        
        @param language_changed: whether the language has changed
        @type language_changed: Boolean
        '''
        # Create garden layer
        self.garden_layer = GardenLayer(self)
        self.add(self.garden_layer, 3)
        
        # Create gui layer
        self.gui_layer = GUILayer(self)
        self.add(self.gui_layer, 250)
        self.remove(self.loading_layer)
        self.paused = False
        
        # Update translated text if desired language has changed
        if language_changed:
            self.reset_text()
        
        # Start the tutorial, if it's on
        if hasattr(self, 'tutorial'):
            self.tutorial.start_tutorial()
        
        # Start the updates
        self.start_update()
        
    def start_update(self):
        '''
        Starts the recurring updates
        '''
        # Schedule game updates
        self.schedule_interval(self.update, 0.02)
        # Schedule background sound changes
        self.schedule_interval(self.play_background_sounds, 5)
    
    def update(self, dt):
        '''
        Updates the different parts of the game
        
        @param dt: time elapsed since last update, in seconds
        @type dt: float
        '''
        # Account for different speeds
        dt /= self.seconds_per_day
        if not self.finished:
            # Increment time
            self._counter += dt
            if self._counter >= 1.0:
                self._increment_day()
                self._counter = 0
            
            # Update weather
            if self.weather.update(dt, self):
                # Weather changed
                self.weather = weather.get_weather(self)
            
            # Update layers
            self.garden_layer.update(dt)
        if not self.finished or self.to_harvest:
            self.gui_layer.update()
        
    def _increment_day(self):
        '''
        Increments the day with one
        '''
        if(self.day+1 > config.DAYS_IN_MONTH[self.month]):
            if(self.month+1 > len(config.MONTHS)-1):
                self.year_end()
                return
            self.day = 1
            self.month += 1
            self.garden_layer.new_month(self.month)
            self.weather.new_month()
        self.day += 1
        
    def play_background_sounds(self, dt):
        '''
        Plays background sounds
        
        @param dt: time elapsed since last update, in seconds
        @type dt: float
        '''
        if self.scene.is_music_busy():
            return
        # Bird twitter
        sound = config.BACKGROUND_SOUNDS[random.randrange(0, len(config.BACKGROUND_SOUNDS))]
        self.scene.load_music(util.get_sound_path(sound))
        self.scene.play_music(fade_in=500)
            
    def resetValues(self, full_reset=True):
        '''
        Resets the game to starting values
        
        @param full_reset: whether to reset all values
        @type full_reset: boolean
        '''
        # Reset to starting values
        self.seconds_per_day = Game.START_SECONDS_PER_DAY
        self.day = Game.START_DAY
        self.month = Game.START_MONTH
        self.base_temperature = config.AVERAGE_SOIL_TEMPS[self.month]
        self.temperature = self.base_temperature
        if full_reset:
            self.year = Game.START_YEAR
            self.total_score = Game.START_TOTAL_SCORE
        self.year_score = Game.START_YEAR_SCORE
        self.harvested = []
        self.to_harvest = 0
        self.finished = False
        self.ended = False
        if hasattr(self, 'tutorial') and self.tutorial:
            self.tutorial.end_tutorial()
            self.tutorial = None
        
    def restartGame(self, new_year=False, tutorial=False, language_changed=False):
        '''
        Restarts the game
        
        @param new_year: whether to restart in a new year
        @type new_year: boolean
        
        @param tutorial: whether to restart with the tutorial
        @type tutorial: boolean
        '''
        self.stop()
        self.resetValues(not new_year)
        self.garden_layer.resetLayer()
        self.gui_layer.resetLayer()
        self.reset_selection()
        self.gui_layer.update_score()
        self.resumeGame(not new_year, language_changed)
        if new_year:
            self.start_update()
        elif tutorial:
            # Tutorial
            self.tutorial = events.Tutorial(self)
            self.tutorial.start_tutorial()
        
    def year_end(self):
        '''
        Ends the current year
        '''
        if not self.finished:
            self.finished = True
            self.pauseGame()
            self.unschedule(self.update)
            self.unschedule(self.play_background_sounds)
            self.reset_selection()
        # Harvest everything that isn't yet harvested
        for bed in self.garden_layer.beds:
            for plant in bed.plants:
                bed.harvest(plant)
                # Play sound
                self.gui_layer.menu.harvest_tool.use(bed, 0, 0, 0, None)
        
        # Wait on actions
        if self.to_harvest:
            pyglet.clock.schedule_once(lambda dt: self.year_end(), 1)
            return
        
        # Add up total score
        self.total_score += self.year_score
        
        # Show year end background
        director.replace(EndLayer(self).scene)
        
    def new_year(self):
        '''
        Starts a new year
        '''
        self.year += 1
        director.replace(self.scene)
        self.restartGame(True)
        
    def pauseGame(self):
        '''
        Pauses the game
        '''
        self.paused = True
        self.pause()
        if self.selected_tool != None:
            self.selected_tool.cancel()
        self.pause_scheduler()
        
    def resumeGame(self, push_in=False, language_changed=False):
        '''
        Resumes the game
        
        @param push_in: whether to push a scene to the director
        @type pysh_in: boolean
        '''
        if language_changed:
            # Update translated text
            self.reset_text()
        if hasattr(self, "tutorial") and self.tutorial and self.tutorial.visible:
            self.tutorial.reset_text()
        if push_in:
            if self.finished:
                director.push(EndLayer(self).scene)
            else:
                director.push(self.scene)
        if not self.finished:
            self.paused = False
        if not push_in:
            self.resume()
            self.resume_scheduler()
    
    def select_seed(self, seed, x, y):
        '''
        Selects a seed
        
        @param seed: the seed to select
        @type seed: Plant.__class__
        
        @param x: the x-coordinate of the click
        @type x: float
        
        @param y: the y-coordinate of the click
        @type y: float
        '''
        self.reset_selection()
        self.selected_seed = seed
        director.interpreter_locals["director"].window.set_mouse_cursor(seed.get_cursor())
        mii = seed.get_mouse_info_image()
        if mii:
            self.set_mouse_info_image(mii, x, y)
        
    def select_tool(self, tool, x, y):
        '''
        Selects a tool
        
        @param tool: the tool to select
        @type tool: Tool
        
        @param x: the x-coordinate of the click
        @type x: float
        
        @param y: the y-coordinate of the click
        @type y: float
        '''
        self.reset_selection()
        self.selected_tool = tool
        director.interpreter_locals["director"].window.set_mouse_cursor(tool.get_cursor())
        mii = tool.get_mouse_info_image()
        if mii:
            self.set_mouse_info_image(mii, x, y)
            
    def reset_selection(self):
        '''
        Resets the current selection
        '''
        self.selected_seed = None
        if self.selected_tool:
            self.selected_tool.cancel()
            self.selected_tool = None
        self.reset_mouse_info_image()
        director.interpreter_locals["director"].window.set_mouse_cursor(pyglet.window.BaseWindow.CURSOR_DEFAULT)
        
    def set_mouse_info_image(self, image, x, y):
        '''
        Sets the mouse info image, the image that follows the mouse
        
        @param image: the image to set
        @type image: Gardensprite
        
        @param x: the x-coordinate of the click
        @type x: float
        
        @param y: the y-coordinate of the click
        @type y: float
        '''
        self.mouse_info_image = image
        self.add(image, 150)
        self.mouse_info_image.position = x,y
    
    def reset_mouse_info_image(self):
        '''
        Resets the mouse info image
        '''
        if self.mouse_info_image:
            self.remove(self.mouse_info_image)
            self.mouse_info_image = None
        
    def harvest(self, plant):
        '''
        Harvests the supplied plant
        
        @param plant: the plant to harvest
        @type plant: Plant
        '''
        # Harvest animation
        # Show basket
        self.to_harvest += 1
        basket = self.gui_layer.harvest_basket
        basket_front = self.gui_layer.basket_front
        fade = actions.FadeIn(0.5)
        basket.do(fade)
        basket_front.do(fade)
        new_pos = plant.point_to_world(euclid.Vector2(plant.x, plant.y))
        plant.kill()
        plant.position = new_pos
        plant.harvest()
        self.gui_layer.add(plant, z=63)
        next = actions.CallFunc(lambda: self._harvest_next(basket, basket_front, plant))
        jump = actions.JumpTo(position=(basket.x,basket.y-20), jumps=1, duration=1, height=300)
        rotate = actions.RotateBy(-360, .8)
        plant.do((jump | rotate) + next)
        
    def _harvest_next(self, basket, front, plant):
        '''
        A follow-up function to harvest(plant)
        
        @param basket: the harvest basket
        @type basket: Gardensprite
        
        @param front: the front of the harvest basket
        @type front: Gardensprite
        
        @param plant: the plant to harvest
        @type plant: Plant
        '''
        next = actions.CallFunc(lambda: self._harvest_done(plant))
        fade = actions.FadeOut(0.5)
        basket.do(fade)
        front.do(fade)
        plant.do(fade + next)
    
    def _harvest_done(self, plant):
        '''
        The final function in the harvest-routine
        
        @param plant: the plant to harvest
        @type plant: Plant
        '''
        self.harvested.append(plant)
        plant.kill();
        self.year_score += int(round(plant.score))
        self.gui_layer.update_score()
        self.to_harvest -= 1
        
    def reset_text(self):
        '''
        Resets translated text
        '''
        self.gui_layer.reset_text()
    
    def on_mouse_press(self, x, y, button, modifiers):
        if self.paused:
            return
        # Delegate mouse press to children layers
        # First gui layer to see if window overlays are open
        if not self.gui_layer.on_mouse_press(x, y, button, modifiers):
            self.garden_layer.on_mouse_press(x, y, button, modifiers)
    
    def on_mouse_release(self, x, y, button, modifiers):
        if self.paused:
            return
        # Delegate mouse release to children layers
        # First gui layer to see if window overlays are open
        if not self.gui_layer.on_mouse_release(x, y, button, modifiers):
            self.garden_layer.on_mouse_release(x, y, button, modifiers)
            
    def on_mouse_motion(self, x, y, dx, dy):
        # Update mouse info image
        if self.mouse_info_image != None:
            self.mouse_info_image.position = x, y
        # Delegate to layers
        if self.paused:
            return
        if not self.gui_layer.on_mouse_motion(x, y, dx, dy):
            self.garden_layer.on_mouse_motion(x, y, dx, dy)
            
    def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
        # Update mouse info image
        if self.mouse_info_image != None:
            self.mouse_info_image.position = x, y
        # Delegate to layers
        if self.paused:
            return
        self.garden_layer.on_mouse_drag(x, y, dx, dy, button, modifiers)
    
    def on_key_press(self, symbol, modifiers):
        if symbol == key.PLUS:
            if self.paused:
                return True
            if self.seconds_per_day > 1.0:
                self.seconds_per_day -= 1.0
            else:
                self.seconds_per_day /= 2.0
            if self.seconds_per_day < 0.0625: self.seconds_per_day = 0.0625
            return True
        elif symbol == key.MINUS:
            if self.paused:
                return True
            if self.seconds_per_day < 1.0:
                self.seconds_per_day *= 2.0
            else:
                self.seconds_per_day += 1.0
            if self.seconds_per_day > 5.0: self.seconds_per_day = 5.0
            return True
        elif symbol == key.P or symbol == key.PAUSE:
            if self.finished:
                return True
            self.paused = not self.paused
            if self.paused:
                self.pauseGame()
                self.gui_layer.showInfo(_("paused"))
            else:
                self.resumeGame()
                self.gui_layer.hideInfo()
            return True
        elif symbol == key.Q:
            if self.paused:
                return True
            self.year_end()
            return True
        elif symbol == pyglet.window.key.S and (modifiers & pyglet.window.key.MOD_ACCEL):
            # Screenshot
            dir = pyglet.resource.get_settings_path('MyGarden')
            if not os.path.exists(dir):
                os.makedirs(dir)
            filename = os.path.join(dir, 'MyGarden-%d.png')
            self.gui_layer.showInfo(_("screenshot_saved"), 2.5)
            pyglet.image.get_buffer_manager().get_color_buffer().save(filename % (int( time.time() ) ) )
            return True
        elif symbol == pyglet.window.key.ESCAPE:
            if not self.finished:
                director.pop()
                return True
        else:
            # Always return true to ignore DefaultHandler
            # We handle all key presses here
            return True

class GardenLayer(layer.ColorLayer):
    '''
    A layer containing the garden with the beds
    '''
    
    def __init__(self, game):
        '''
        Constructor
        '''
        # Set background colour
        super(GardenLayer, self).__init__(20, 240, 15, 255);
        # Create a background
        grass = sprite.Sprite(util.load_image('grass.jpg'))
        grass.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2
        self.add(grass, z=0)
        
        # Add four beds
        self.beds = []
        self.load_bed(400, 1)
        self.load_bed(275, 2)
        self.load_bed(150, 3)
        self.load_bed(25, 4)
        
    def new_month(self, month):
        '''
        Update the layer with the new month
        
        @param month: the new month
        @type month: int
        '''
        for bed in self.beds:
            bed.temperature = config.AVERAGE_SOIL_TEMPS[month]
    
    def on_mouse_motion(self, x, y, dx, dy):
        for bed in self.beds:
            bed.on_mouse_motion(x, y, dx, dy)
    
    def on_mouse_press(self, x, y, button, modifiers):
        for bed in self.beds:
            bed.on_mouse_press(x, y, button, modifiers)
    
    def on_mouse_release(self, x, y, button, modifiers):
        if(Game().selected_tool != None):
            Game().selected_tool.cancel()
        
    def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
        for bed in self.beds:
            if bed.on_mouse_drag(x, y, dx, dy, button, modifiers):
                break
    
    def update(self, dt):
        '''
        Updates the layer
        
        @param dt: time elapsed since last update, in seconds
        @type dt: float
        '''
        for bed in self.beds:
            bed.update(dt)
    
    def load_bed(self, y, z_value):
        '''
        Loads the beds of this layer
        
        @param y: the y-coordinate of the bed
        @type y: int/float
        
        @param z_value: the z value of the bed
        @type z_value: int
        '''
        b = bed.Bed();
        b.scale = 0.85
        b.image_anchor = 0,0
        b.position = 123, y
        self.add(b, z=z_value);
        self.beds.append(b)
        
    def resetLayer(self):
        '''
        Resets the layer
        '''
        for bed in self.beds:
            bed.resetBed()

class GUILayer(layer.Layer):
    '''
    A layer containing the GUI elements
    '''
    
    def __init__(self, game):
        super(GUILayer, self).__init__()
        self.game = game
        
        # Date label
        self.date_text = _("year")+" %(year)d - %(day)d %(month)s" % \
                {"year": game.year, "day": game.day, "month": config.MONTHS[game.month]}
        self.dateDisplay = text.Label(text=self.date_text,
                                       font_name='Carousel',
                                       font_size=24,
                                       anchor_x='left',
                                       anchor_y='center')
        self.dateDisplay.position = 120, config.SCREEN_HEIGHT-40;
        self.add(self.dateDisplay)
        
        # Score label
        self.score_text = _("score")+" %(score)d" % \
                {"score": game.year_score}
        self.scoreDisplay = text.Label(text=self.score_text,
                                       font_name='Carousel',
                                       font_size=24,
                                       anchor_x='left',
                                       anchor_y='center')
        self.scoreDisplay.position = 475, config.SCREEN_HEIGHT-40;
        self.add(self.scoreDisplay)
        
        # Middle info label
        self.info_text = _("paused")
        self.infoDisplay = text.Label(text=self.info_text,
                                       font_name='Carousel',
                                       font_size=36,
                                       anchor_x='center',
                                       anchor_y='center')
        self.infoDisplay.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2+90;
        self.infoDisplay.visible = False
        self.add(self.infoDisplay, 600)
        self.hiding_info = False
        
        # Tool tip
        self.tooltip = menu.ToolTip("")
        self.tooltip.opacity = 0
        # Current object for which the tooltip is showing
        self.current_tooltip = None
        
        # Left side menu
        self.menu = menu.GameMenu()
        self.add(self.menu, 50)
        
        # Harvest basket
        self.harvest_basket = gardensprite.GardenSprite("basket.png")
        self.harvest_basket.scale = .75
        self.harvest_basket.position = self.harvest_basket.width/2+20,\
            self.harvest_basket.height/2+20
        self.basket_front = gardensprite.GardenSprite("harvest_basket_front.png")
        self.basket_front.scale = self.harvest_basket.scale
        self.basket_front.position = self.harvest_basket.position
        self.basket_front.opacity = 0
        self.add(self.basket_front, z=65)
        self.harvest_basket.opacity = 0
        self.add(self.harvest_basket, z=60)
        
        # Weather window
        self.weather_window = WeatherWindow(game.weather.icon, game.temperature)
        self.add(self.weather_window, z=240)
        
    def showInfo(self, text, timer=None):
        '''
        Shows information in a text box
        
        @param text: the text to show
        @type text: string
        
        @param timer: a timer for hiding the text box
        after the specified number of seconds
        @type timer: int
        '''
        self.infoDisplay.element.text = text
        if self.infoDisplay.visible: return
        self.infoDisplay.do(actions.Show() + actions.FadeIn(.5))
        if timer:
            self.hiding_info = True
            pyglet.clock.schedule_once(lambda dt: self.hideInfo(), timer)
    
    def hideInfo(self):
        '''
        Hides the text box with information
        '''
        if not self.infoDisplay.visible: return
        def done_hiding():
            self.hiding_info = False
        self.infoDisplay.do(actions.FadeOut(.5) + actions.Hide() + actions.CallFunc(done_hiding))
        
    def showTooltip(self, over, x, y):
        '''
        Shows a tooltip
        
        @param over: the object to get tooltip information from
        @type over: object
        
        @param x: x-coordinate to display tooltip at
        @type x: int/float
        
        @param y: y-coordinate to display tooltip at
        @type y: int/float
        '''
        if self.current_tooltip == over:
            x -= self.tooltip.anchor_x
            y -= self.tooltip.anchor_y
            if x+self.tooltip.width > config.SCREEN_WIDTH:
                x = config.SCREEN_WIDTH-self.tooltip.width
            elif x < 0:
                x = 0
            if y-self.tooltip.height < 0:
                y = self.tooltip.height
            elif y > config.SCREEN_HEIGHT:
                y = config.SCREEN_HEIGHT
            self.tooltip.position = x,y
            return
        text = over.tooltip_text
        font = self.tooltip.label.element.document.get_font(None)
        width = util.get_text_width(font, text)+20
        if width < self.tooltip.label.element.width:
            self.tooltip.width = width
        else:
            self.tooltip.width = self.tooltip.label.element.width+20
        self.tooltip.height = util.get_text_height(font, text, self.tooltip.width-20)+20
        self.tooltip.anchor = 0,self.tooltip.height
        
        x -= self.tooltip.anchor_x
        y -= self.tooltip.anchor_y
        if x+self.tooltip.width > config.SCREEN_WIDTH:
            x = config.SCREEN_WIDTH-self.tooltip.width
        elif x < 0:
            x = 0
        if y-self.tooltip.height < 0:
            y = self.tooltip.height
        elif y > config.SCREEN_HEIGHT:
            y = config.SCREEN_HEIGHT
        self.tooltip.position = x,y
        
        self.tooltip.label.y = self.tooltip.height-10
        
        self.tooltip.stop()
        self.current_tooltip = over
        self.tooltip.setText(text)
        if self.tooltip in self.get_children():
            self.remove(self.tooltip)
        self.add(self.tooltip, z=250)
        self.tooltip.do(actions.FadeTo(180, .2))
    
    def hideTooltip(self):
        '''
        Hides the tooltip
        '''
        if self.current_tooltip == None: return
        self.tooltip.stop()
        self.tooltip.do(actions.FadeTo(0, .2) + actions.CallFunc(lambda: self.remove(self.tooltip)))
        self.current_tooltip = None
    
    def update(self):
        '''
        Updates this layer
        '''
        # Update time info
        year_text = _("year")+" %(year)d - %(day)d %(month)s" % \
                {"year": self.game.year, "day": self.game.day, "month": config.MONTHS[self.game.month]}
        self.dateDisplay.element.text = year_text
        # Update temperature
        self.weather_window.update_temperature(self.game.temperature)
    
    def update_score(self):
        '''
        Updates the score display
        '''
        # Update score info
        score_text = _("score")+" %(score)d" % \
                {"score": self.game.year_score}
        self.scoreDisplay.element.text = score_text
        
    def on_mouse_press(self, x, y, button, modifiers):
        # Check game menu
        return self.menu.on_mouse_press(x, y, button, modifiers)
    
    def on_mouse_release(self, x, y, button, modifiers):
        return False
    
    def on_mouse_motion(self, x, y, dx, dy):
        if (self.menu.on_mouse_motion(x, y, dx, dy)
            or self.weather_window.on_mouse_motion(x, y, dx, dy, self)):
            return True
        else:
            self.hideTooltip()
            return False
        
    def resetLayer(self):
        '''
        Resets the layer
        '''
        self.hideInfo()
        self.menu.resetMenu()
        
    def update_weather(self, weather):
        '''
        Updates the weather
        
        @param weather: the new weather
        @type weather: Weather
        '''
        self.weather_window.change_weather(weather)
    
    def reset_text(self):
        '''
        Resets all translated text
        '''
        # Update score text
        self.update_score()
        self.weather_window.reset_text()
        self.menu.reset_text()
        
class WeatherWindow(gardensprite.GardenSprite):
    '''
    Small window for showing the current weather
    '''
    def __init__(self, weather_icon, temp):
        super(WeatherWindow, self).__init__("weather_frame.png")
        self.scale = .7
        self.position = config.SCREEN_WIDTH-self.width/2, config.SCREEN_HEIGHT-self.height/2
        # Add weather icon
        self.weather_icon = weather_icon
        self.add(weather_icon, z=1)
        # Add temperature label
        self.temp_label = text.RichLabel(unicode(str(temp)+"°C", "UTF-8"),
                                         color=(0,0,0,255),
                                         font_name='Carousel',
                                         font_size=24,
                                         anchor_x='left',
                                         anchor_y='top')
        self.temp_label.position = -self.width/2+3, self.height/2-1
        self.add(self.temp_label, z=2)
        # Tooltip text
        self.tooltip_text = _("weather_soil_temperature")
        
    def change_weather(self, weather):
        '''
        Changes the weather display
        
        @param weather: the weather to show
        @type weather: Weather
        '''
        if self.weather_icon == weather.icon:
            return
        self.weather_icon.stop()
        self.remove(self.weather_icon)
        self.weather_icon = weather.icon
        self.weather_icon.opacity = 0
        self.add(self.weather_icon, z=1)
        self.weather_icon.do(actions.FadeIn(1))
        
    def update_temperature(self, temp):
        '''
        Updates the temperature
        
        @param temp: the new temperature
        @type temp: int/float
        '''
        self.temp_label.element.text = unicode(str(int(round(temp)))+"°C", "UTF-8")
    
    def reset_text(self):
        '''
        Resets translated text
        '''
        self.tooltip_text = _("weather_soil_temperature")
        
    def on_mouse_motion(self, x, y, dx, dy, gui):
        if self.is_over(x, y):
            gui.showTooltip(self, x, y)
            return True
        return False
    
class Loader(layer.ColorLayer):
    '''
    A layer for giving notice that something is loading
    '''

    def __init__(self):
        '''
        Constructor
        '''
        super(Loader, self).__init__(20,20,20,255);
        
        self.carrot = sprite.Sprite(util.load_image('loading_carrot.png'))
        self.carrot.position = 400,280
        self.add(self.carrot)
        
        # Label
        self.info_text = _("please_wait")
        self.infoDisplay = text.Label(text=self.info_text,
                                       font_name='Carousel',
                                       font_size=36,
                                       anchor_x='center',
                                       anchor_y='center')
        self.infoDisplay.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2+150;
        self.add(self.infoDisplay, 300)
        
class EndLayer(layer.Layer):
    '''
    Layer shown when a year has ended
    '''
    
    def __init__(self, game):
        '''
        Constructor
        '''
        super(EndLayer, self).__init__()
        
        # Set up background and table
        grass = sprite.Sprite(util.load_image('grass.jpg'))
        grass.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2
        self.add(grass, z=0)
        table = sprite.Sprite(util.load_image('table.png'))
        table.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2-table.height
        self.add(table, z=1)
        
        # Place all harvested food on the table
        for food in game.harvested:
            food.opacity = 255
            food.position = (random.randrange(-250, 250), random.randrange(19, 79))
            rotation = random.randrange(food.min_rotation, food.max_rotation)
            food.rotation = rotation if rotation >= 0 else rotation+360
            table.add(food)
            
        # Show harvested amount and score
        text_layer = layer.ColorLayer(220, 220, 200, 140)
        text_layer.width = int(config.SCREEN_WIDTH*0.7)
        text_layer.height = int(config.SCREEN_HEIGHT*0.5)
        text_layer.position = (config.SCREEN_WIDTH-text_layer.width)/2, config.SCREEN_HEIGHT-text_layer.height-20
        text_layer.anchor = 0,0
        self.add(text_layer, 50)
        
        title_text = _("score")
        title_label = text.Label(text=title_text,
                                       font_name='Carousel',
                                       font_size=44,
                                       anchor_x='center',
                                       anchor_y='center')
        title_label.position = text_layer.width/2, text_layer.height-40;
        text_layer.add(title_label, 50)
        
        score_text = _("score_this_year")+": %(score)d" % \
                {"score": game.year_score}
        score_label = text.Label(text=score_text,
                                       font_name='Carousel',
                                       font_size=36,
                                       anchor_x='center',
                                       anchor_y='center')
        score_label.position = text_layer.width/2, text_layer.height-100;
        text_layer.add(score_label, 50)
        
        total_text = _("score_total")+": %(total)d" % \
                {"total": game.total_score}
        total_label = text.Label(text=total_text,
                                       font_name='Carousel',
                                       font_size=32,
                                       anchor_x='center',
                                       anchor_y='center')
        total_label.position = text_layer.width/2, text_layer.height-150;
        text_layer.add(total_label, 50)
        
        harvested_text = _("harvested_vegetables")+": %(harvested)d" % \
                {"harvested": len(game.harvested)}
        harvested_label = text.Label(text=harvested_text,
                                       font_name='Carousel',
                                       font_size=32,
                                       anchor_x='center',
                                       anchor_y='center')
        harvested_label.position = text_layer.width/2, text_layer.height-220;
        text_layer.add(harvested_label, 50)
        
        # Menu
        self.end_menu = menu.EndMenu(self)
        self.add(self.end_menu, z=3)
        
        # Middle info label
        self.info_text = _("paused")
        self.infoDisplay = text.Label(text=self.info_text,
                                       font_name='Carousel',
                                       font_size=36,
                                       anchor_x='center',
                                       anchor_y='center')
        self.infoDisplay.position = config.SCREEN_WIDTH/2, 190;
        self.infoDisplay.visible = False
        self.add(self.infoDisplay, 600)
        
        if not Game().ended:
            # Check if player made the high scores list
            dir = pyglet.resource.get_settings_path('MyGarden')
            if not os.path.exists(dir):
                os.makedirs(dir)
            filename = os.path.join(dir, 'highscores.txt')
            file = open(filename, 'a+')
            # Go through the scores
            count = 0
            year_scores = []
            total_scores = []
            for line in file.readlines():
                line = line.strip()
                if line[0] != "#":
                    # Format - score:name
                    score = line.split(':')
                    if count < 5:
                        year_scores.append(Score(int(score[0]), score[1]))
                    else:
                        total_scores.append(Score(int(score[0]), score[1]))
                    count += 1
            
            # Add your scores
            year_scores.append(Score(Game().year_score, ""))
            total_scores.append(Score(Game().total_score, ""))
            
            # Sort the scores
            self.year_scores = sorted(year_scores, reverse=True, key=attrgetter('score'))
            self.total_scores = sorted(total_scores, reverse=True, key=attrgetter('score'))
            
            file.close()
            
        Game().ended = True
        
        # Show name text input if you made the highscores
        if hasattr(self, 'year_scores'):
            for s in self.year_scores[:5]+self.total_scores[:5]:
                if s.name == "":
                    theme = kytten.Theme(os.path.join(os.path.dirname(__file__), '../theme'), override={
                        "gui_color": [255, 235, 128, 255],
                        "font_size": 14,
                        "font": 'Carousel'
                    })
                    
                    self.name_input = dialog_node.DialogLayer()
                    dnode = dialog_node.DialogNode(kytten.Dialog(
                        kytten.Frame(
                            kytten.VerticalLayout([
                                kytten.SectionHeader(_("entered_highscores"),
                                         align=kytten.HALIGN_LEFT),
                                kytten.GridLayout([
                                [kytten.Label(_("your_name")), kytten.Input("name", "["+_("your_name")+"]", max_length=15)]
                                ]),
                                kytten.HorizontalLayout([
                                kytten.Button(_("ok"), on_click=lambda: self.save_score(dnode)),
                                ]),
                            ], align=kytten.HALIGN_LEFT)
                        ),
                        window=director.window,
                        anchor=kytten.ANCHOR_CENTER,
                        theme=theme, on_enter=lambda source: self.save_score(dnode)))
                    self.name_input.add_dialog(dnode)
                    self.add(self.name_input, 150)
                    for control in dnode.dialog._get_controls():
                        if isinstance(control[0], kytten.text_input.Input):
                            dnode.dialog.set_focus(control[0])
                            break
                    break
        
        # Scene
        self.scene = scene.Scene()
        self.scene.add(self)
        
    def save_score(self, dnode):
        '''
        Saves the score
        
        @param dnode: the DialogNode to get name information from
        @type dnode: DialogNode
        '''
        name = None
        for control in dnode.dialog._get_controls():
            if isinstance(control[0], kytten.text_input.Input):
                name = control[0].get_text()
                break
        if not name:
            name = _("incognito")
        dir = pyglet.resource.get_settings_path('MyGarden')
        if not os.path.exists(dir):
            os.makedirs(dir)
        filename = os.path.join(dir, 'highscores.txt')
        file = open(filename, 'w')
        
        # Write the first five of each
        scores = [self.year_scores, self.total_scores]
        for score in scores:
            for i in range(5):
                if len(score) > i:
                    if not score[i].name:
                        score[i].name = name
                    file.write(str(score[i].score)+":"+score[i].name+"\n")
                else:
                    file.write("0: - \n")
                    
        file.close()
        
        # Remove input window
        self.remove(self.name_input)
        self.name_input = None
        
        hsl = HighscoreLayer()
        self.add(hsl, z=150)
        
    def showInfo(self, text, timer=None):
        '''
        Shows information in a text box
        
        @param text: the text to show
        @type text: string
        
        @param timer: a timer for hiding the text box
        after the specified number of seconds
        @type timer: int
        '''
        self.infoDisplay.element.text = text
        if self.infoDisplay.visible: return
        self.infoDisplay.do(actions.Show() + actions.FadeIn(.5))
        if timer:
            pyglet.clock.schedule_once(lambda dt: self.hideInfo(), timer)
    
    def hideInfo(self):
        '''
        Hides the text box with information
        '''
        if not self.infoDisplay.visible: return
        self.infoDisplay.do(actions.FadeOut(.5) + actions.Hide())
        
    def on_enter(self):
        super(EndLayer, self).on_enter()
        # Music
        self.scene.load_music(util.get_sound_path('mygarden.ogg'), repeat=-1)
        # Start music
        self.scene.play_music(loops=-1)

class Score(object):
    '''
    An object for holding scores when sorting
    '''
    
    def __init__(self, score, name):
        self.score = score
        self.name = name
        
class HighscoreLayer(layer.ColorLayer):
    '''
    A layer for showing the high scores
    '''
    is_event_handler = True
    
    def __init__(self):
        super(HighscoreLayer, self).__init__(230,230,200,0)
        self.visible = False
        
        self.width = int(config.SCREEN_WIDTH*0.9)
        self.height = int(config.SCREEN_HEIGHT*0.75)
        self.position = config.SCREEN_WIDTH/2-self.width/2, config.SCREEN_HEIGHT/2-self.height/2
        
        # Get the scores
        dir = pyglet.resource.get_settings_path('MyGarden')
        if not os.path.exists(dir):
            os.makedirs(dir)
        filename = os.path.join(dir, 'highscores.txt')
        file = open(filename, 'a+')
        # Go through the scores
        count = 0
        year_scores = []
        total_scores = []
        for line in file.readlines():
            line = line.strip()
            if line[0] != "#":
                # Format - score:name
                score = line.split(':')
                if count < 5:
                    year_scores.append(Score(int(score[0]), score[1]))
                else:
                    total_scores.append(Score(int(score[0]), score[1]))
                count += 1
                
        file.close()
                
        # Show the scores
        self.title = text.Label(_("highscores"), font_name="Carousel", font_size=42, anchor_x='center', color=(50,40,0,255))
        self.title.position = self.width/2, self.height-65
        self.year = text.Label(_("highscore_one_year"), font_name="Carousel", font_size=27, anchor_x='center', color=(50,40,0,255))
        self.year.position = self.width*.3, self.height-125
        self.total = text.Label(_("highscore_total"), font_name="Carousel", font_size=27, anchor_x='center', color=(50,40,0,255))
        self.total.position = self.width*.7, self.height-125
        
        self.add(self.title)
        
        self.add(self.year)
        i = 0
        for score in year_scores:
            i += 1
            label = text.Label(score.name+" - "+str(score.score), font_name="Carousel", font_size=21, anchor_x='center', color=(50,40,0,255))
            label.position = self.year.x, self.year.y-40*i-10
            self.add(label)
        
        self.add(self.total)
        i = 0
        for score in total_scores:
            i += 1
            label = text.Label(score.name+" - "+str(score.score), font_name="Carousel", font_size=21, anchor_x='center', color=(50,40,0,255))
            label.position = self.total.x, self.total.y-40*i
            self.add(label)
            
    def on_mouse_press(self, x, y, button, modifiers):
        self.kill()
        return True
        
    def on_key_press(self, symbol, modifiers):
        if symbol in [pyglet.window.key.ESCAPE, pyglet.window.key.RETURN]:
            self.kill()
            return True
        
    def kill(self):
        def super_kill():
            super(HighscoreLayer, self).kill()
        self.do(actions.FadeTo(0, 0.5)+actions.Hide()+actions.CallFunc(super_kill))
        
    def on_enter(self):
        super(HighscoreLayer, self).on_enter()
        self.do(actions.Show()+actions.FadeTo(230, 0.5))
        
    def reset_text(self):
        '''
        Resets translated text
        '''
        self.title.element._set_text(_("highscores"))
        self.year.element._set_text(_("highscore_one_year"))
        self.total.element._set_text(_("highscore_total"))